home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DJGPP
/
QDDVX102.ZIP
/
contrib
/
dvx
/
qdeck
/
kern
/
scale.c
< prev
Wrap
Text File
|
1993-07-15
|
8KB
|
240 lines
/*----------------------------------------------------------------------*/
/* */
/* Sample usage of scalable font fractional spacing and kerning. */
/* */
/* This file demonstrates how scalable fonts can be used in the */
/* DESQview/X environment. It emphasises how fractional spacing */
/* and kerning are performed. */
/* */
/*----------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xmd.h>
#include <X11/X.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
typedef struct KERNPAIRtag
{
char chLeft;
char chRight;
INT32 xKernOffset;
} KERNPAIR;
Display *dpy;
int screen;
Window root;
GC gcBase;
Window winMain;
KERNPAIR *pKernBase;
XFontStruct *xfn;
/*----------------------------------------------------------------------*/
/* BASIC X OPERATIONS */
/*----------------------------------------------------------------------*/
main ()
{
XSetWindowAttributes xswa;
dpy = XOpenDisplay (NULL);
screen = DefaultScreen(dpy);
root = RootWindow(dpy,screen);
gcBase = DefaultGC(dpy,screen);
winMain = XCreateSimpleWindow (dpy, root, 0, 0, 500, 100, 0, 0L, 15L);
xswa.event_mask = ExposureMask;
XChangeWindowAttributes (dpy, winMain, CWEventMask, &xswa);
XMapWindow (dpy, winMain);
InitText ("Times Roman-Medium-R", 24);
while (1)
{
XEvent xe;
XNextEvent (dpy,&xe);
switch (xe.type)
{
case Expose:
DrawText (10, 50, "This is the string to be printed.");
break;
case DestroyNotify:
ClearText ();
break;
}
}
}
/*----------------------------------------------------------------------*/
/* SAMPLE CODE FOR FRACTIONAL SPACING AND KERNING */
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
/* LOAD FONT AND READ KERNING PAIRS */
/*----------------------------------------------------------------------*/
InitText (char *pszFont, int PointSize)
{
char szName[256];
int xRes;
int yRes;
Atom atomKernLabel, atomKernVar;
XGCValues values;
KERNPAIR *pKern;
Atom atomType;
int iFormat;
long cItems;
long bytes_after;
char *pProp;
char *pPropBase;
int cProps;
xRes = 75;
yRes = 75;
sprintf (szName, "-Adobe-%s-Normal--*-%d-%d-%d-*-*-*-Adobe",
pszFont, PointSize*10, xRes, yRes);
xfn = XLoadQueryFont (dpy, szName); /* load the font */
if (!xfn)
{
printf("Could not load font \"%s\".\n",szName);
exit(1);
}
else
{
values.font = xfn->fid;
XChangeGC (dpy, gcBase, GCFont, &values);
/* Now we want to grab the kerning pairs. This is done by looking at the */
/* font property 'KERNING_PAIRS' to find the root windows property name. */
/* The root property is next examined to extract the needed pairs. The */
/* pairs are transferred into an array. */
atomKernLabel = XInternAtom (dpy, "KERNING_PAIRS", 0);/* enumerate prop */
XGetFontProperty (xfn, atomKernLabel, &atomKernVar); /* grab root name */
XGetWindowProperty (dpy, root, atomKernVar, 0, 8192, /* get the info */
False, AnyPropertyType, &atomType, &iFormat, &cItems, &bytes_after, &pProp);
pPropBase = pProp;
cProps = *(INT16 *)pProp; pProp+=2; /* get number of properties */
pKern = (KERNPAIR *)malloc (sizeof(KERNPAIR) * (cProps+1));
pKernBase = pKern;
while (cProps--)
{
pKern->chLeft = *pProp++; /* left character in pair */
pKern->chRight = *pProp++; /* right character in pair */
pKern->xKernOffset = (INT32)(*(INT16 *)pProp) + ((INT32)(*(INT16 *)(pProp+2)))*65536L;
pProp += 4;
pKern++;
}
pKern->chLeft = 0; /* mark end of table */
pKern->chRight = 0;
pKern->xKernOffset = 0;
XFree (pPropBase); /* we are done with the data */
}
}
/*----------------------------------------------------------------------*/
/* UNLOAD FONT AND KERNING PAIRS */
/*----------------------------------------------------------------------*/
ClearText ()
{
free (pKernBase); /* free kerning stuff */
XFreeFont (dpy, xfn); /* get rid of font */
}
/*----------------------------------------------------------------------*/
/* FIND PAIR OF CHARACTERS IN KERNING ARRAY */
/*----------------------------------------------------------------------*/
/* This routine just does a simple sequential search to find the kerning */
/* pair. A better implementation would be to sort the array and perform */
/* binary searches. */
INT32 LookupKern (char chLeft, char chRight)
{
KERNPAIR *pKern;
pKern = pKernBase;
while (pKern->chLeft)
{
if ((pKern->chLeft == chLeft) && (pKern->chRight == chRight))
return (pKern->xKernOffset); /* return delta */
pKern++;
}
return (0L); /* no pair -> delta = 0 */
}
/*----------------------------------------------------------------------*/
/* OUTPUT ONE LINE OF TEXT WITH KERNING + FRACTIONAL SPACING */
/*----------------------------------------------------------------------*/
/* This routine performs fractional spacing and kering as described */
/* in the documentation. A series of XTextItem text chunks is output */
/* with delta "corrections" to compensate for the difference between */
/* rouded integer spacing and fractional spacing. */
DrawText (int xPos, int yPos, char *pszText)
{
char chPrev; /* previous character */
XTextItem ati[100]; /* XTextItem array for cummulation */
int cItems; /* count of XTextItem entries */
INT16 xPosRound; /* running x position as rounded integer */
INT32 xPosFixed; /* running x position as 16.16 fixed nota'n */
char *pszBase; /* running pointer to base of text chunk */
INT16 DeltaInt; /* rounded integer character width */
INT16 DeltaFrac; /* signed fractional part of character wid. */
INT16 xPosCheck; /* variable fo comparing widths */
int cChars; /* number of charcters in XTextItem entry */
cChars = 0; /* initialize some stuff */
chPrev = 0;
xPosRound = 0;
xPosFixed = 0;
cItems = 0;
pszBase = pszText;
ati[0].delta = 0;
while (*pszText)
{
xPosFixed += LookupKern (chPrev, *pszText); /* make kerning adjustment */
xPosCheck = (INT16)((xPosFixed+32768L)>>16); /* get round (16.16) */
if (xPosCheck != xPosRound) /* is "correction" necessary? */
{
ati[cItems].chars = pszBase; /* sequence of characters to output */
ati[cItems].nchars = cChars; /* number of characters to output */
ati[cItems+1].delta = xPosCheck - xPosRound; /* how much of an adjmnt */
ati[cItems].font = 0; /* we want to use the current font */
xPosRound = xPosCheck; /* "correct" the running rounded x pos */
pszBase = pszText; /* next text chunk will start here */
cChars = 0; /* reset count for next chunk */
cItems++; /* increment XTextItem counter */
}
DeltaInt = xfn->per_char[(INT16)*pszText - xfn->min_char_or_byte2].width;
DeltaFrac = xfn->per_char[(INT16)*pszText - xfn->min_char_or_byte2].attributes;
xPosRound += DeltaInt; /* update running x counters */
xPosFixed += (((INT32)DeltaInt)<<16) + (INT32)DeltaFrac;
cChars++; /* note that (INT32)DeltaFrac is signed */
chPrev = *pszText++; /* so that it can both lower and raise DeltaInt */
}
ati[cItems].chars = pszBase; /* final XTextItem chunk */
ati[cItems].nchars = cChars;
ati[cItems].font = 0;
cItems++;
/* now, we actually print out the results of the above calculations */
XDrawText (dpy, winMain, gcBase, xPos, yPos, ati, cItems);
}